package com.bds.snatch.system.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.nutz.dao.Chain;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.dao.impl.NutDao;
import org.openqa.selenium.By;
import org.openqa.selenium.Dimension;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bds.snatch.model.H2Urls;
import com.bds.snatch.model.Template;
import com.bds.snatch.model.TemplateDetail;
import com.bds.snatch.model.TemplateUrl;
import com.bds.snatch.model.Tresult;
import com.bds.snatch.system.queue.TQueue;
import com.bds.snatch.system.util.Const;
import com.bds.snatch.system.util.PhantomjsUtilV2;
import com.bds.snatch.system.util.SpringContextHolder;

@Service("parseService")
public class ParseService {
	private static final Logger LOGGER = Logger.getLogger(ParseService.class);
	@Resource
	private Dao dao;
	@Resource
	private BalanceService balanceService;
	@Resource
	private MessageService messageService;

	public void parseHtml(Long id, Document doc, Dao h2dao, boolean isdel) {
		NutDao apiDao = SpringContextHolder.getBean("dao");
		try {

			apiDao.update(TemplateUrl.class, Chain.make("status", 4), Cnd.where("id", "=", id));
			TemplateUrl taskPage = apiDao.fetch(TemplateUrl.class, Cnd.where("id", "=", id));

			Template temp = apiDao.fetch(Template.class, Cnd.where("request_id", "=", taskPage.getRequest_id()));
			LOGGER.info("#########开始解析" + taskPage.getRequest_id() + "," + taskPage.getOrderby() + "##############");
			try {

				JSONArray array = this.parseVal(doc, temp.getRequest_id(), taskPage.getUrl(), h2dao);

				for (int i = 0; i < array.size(); i++) {
					JSONObject json = array.getJSONObject(i);

					Tresult r = new Tresult();
					try {
						r.setCreate_time(new Date());
						r.setName(temp.getTemplate_name());
						r.setRequest_id(taskPage.getRequest_id());
						r.setUser_id(taskPage.getUser_id());
						r.setResult(json.toJSONString());
						r.setUrl_id(taskPage.getId());
						apiDao.fastInsert(r);
					} catch (Exception e) {
						e.printStackTrace();
					}
				}

				apiDao.updateIgnoreNull(taskPage);

				/** 解析成功 */
				apiDao.update(TemplateUrl.class, Chain.make("status", 5), Cnd.where("id", "=", taskPage.getId()));

				if (isdel&&h2dao!=null) {
					h2dao.delete(H2Urls.class, taskPage.getId());
				}
				balanceService.subtractBalance(taskPage.getUser_id(), 1.0);
				LOGGER.info("#########页解析成功" + taskPage.getRequest_id() + "##############");
			} catch (Exception e) {

				if (isdel&&h2dao!=null) {
					h2dao.delete(H2Urls.class, taskPage.getId());
				}
				LOGGER.error("", e);
				apiDao.update(TemplateUrl.class, Chain.make("status", 6), Cnd.where("id", "=", taskPage.getId()));
			}

		} catch (Exception e) {
			if (isdel&&h2dao!=null) {
				h2dao.delete(H2Urls.class, id);
			}
			LOGGER.error("", e);
			/** 解析失败 */
			apiDao.update(TemplateUrl.class, Chain.make("status", 6), Cnd.where("id", "=", id));
		}
	}

	public JSONArray parseVal(Document doc, String request_id, String url, Dao h2dao) throws Exception {
		NutDao apiDao = SpringContextHolder.getBean("dao");
		JSONArray array = new JSONArray();
		Template temp = apiDao.fetch(Template.class, Cnd.where("request_id", "=", request_id));
		java.net.URL netUrl = new java.net.URL(temp.getUrl());
		LOGGER.info("#########开始解析" + request_id + "##############");
		try {

			List<TemplateDetail> all = apiDao.query(TemplateDetail.class,
					Cnd.where("request_id", "=", request_id).asc("orderby"));

			Map<String, TemplateDetail> map = new LinkedHashMap<String, TemplateDetail>();
			List<String[]> extList = new ArrayList<String[]>();
			String[] head = temp.getHead().split(",");
			for (TemplateDetail td : all) {
				String key = td.getPropert();
				if (!map.containsKey(key)) {
					map.put(key, td);
				}
			}
			for (String h : head) {
				if (!map.containsKey(h)) {
					map.put(h, null);
				}
			}

			int exts = 0;

			if (StringUtils.isNotEmpty(temp.getExts())) {
				String[] ar = temp.getExts().split(",");
				exts = ar.length;
				for (String ks : ar) {
					extList.add(ks.split("\\|"));
				}
			}

			// Task task = apiDao.fetch(Task.class, Cnd.where("request_id",
			// "=", taskPage.getRequest_id()));

			Set<String> keys = map.keySet();
			for (String k : keys) {

				TemplateDetail detail = map.get(k);

				if (detail == null) {
					continue;
				}
				String attr = detail.getAttr();
				if (detail.getColumn_type().equals("list")) {
					String nodePath = "";
					if (StringUtils.isEmpty(detail.getNode_path())) {
						nodePath = "";
					} else {
						nodePath = detail.getNode_path();
					}
					Elements es = doc.select(detail.getList_path() + nodePath);

					for (int i = 0; i < es.size(); i++) {
						Element e = es.get(i);
						String value = "";
						value = this.getValue(attr, e);
						if (attr.equals("href")) {
							if (value.startsWith("/")) {
								value = "http://" + netUrl.getHost() + value;
							} else if (value.startsWith(".")) {
								value = value.substring(1, value.length());
								if (value.startsWith("/")) {
									value = "http://" + netUrl.getHost() + value;
								} else {
									value = "http://" + netUrl.getHost() + "/" + value;
								}
							}else{
								if(value.indexOf("http://")<0){
									value = "http://" + netUrl.getHost() + "/" + value;
								}
							}
						}
						if (StringUtils.isNotEmpty(detail.getLink()) && detail.getAttr().equals("href")) {
							this.getChildPage(detail.getLink(), detail.getUser_id(), h2dao, value, i);
						}

						if ((i + 1) > array.size()) {
							JSONObject json = new JSONObject();
							json.put(k, value);
							if (StringUtils.isNotEmpty(detail.getLink())) {
								JSONObject link = new JSONObject();
								JSONObject var = new JSONObject();
								var.put("url", value);
								var.put("rid", detail.getLink());
								link.put(k, var);
								json.put("link", link);
							}
							array.add(json);
						} else {
							JSONObject json = array.getJSONObject(i);
							json.put(k, value);
							if (StringUtils.isNotEmpty(detail.getLink())) {
								JSONObject link = json.getJSONObject("link");
								if (link == null) {
									link = new JSONObject();
								}
								JSONObject var = link.getJSONObject(k);
								if (var == null) {
									var = new JSONObject();
								}
								var.put("url", value);
								var.put("rid", detail.getLink());
								link.put(k, var);
								json.put("link", link);
							}
						}

					}

				}
			}
			LOGGER.info("#########页面解析列表-LIST完成" + request_id + "##############");
			/**
			 * 处理单元素
			 */

			for (String k : keys) {

				TemplateDetail detail = map.get(k);
				if (detail == null) {
					continue;
				}
				String attr = detail.getAttr();

				if (detail.getColumn_type().equals("element")) {
					String path = detail.getNode_path();
					Elements es = doc.select(path);
					Element e = es.first();
					String value = "";
					if (e == null) {
						value = "";
					} else {
						value = this.getValue(attr, e);
						if (attr.equals("href")) {
							if (value.startsWith("/")) {
								value = "http://" + netUrl.getHost() + value;
							} else if (value.startsWith(".")) {
								value = value.substring(1, value.length());
								if (value.startsWith("/")) {
									value = "http://" + netUrl.getHost() + value;
								} else {
									value = "http://" + netUrl.getHost() + "/" + value;
								}
							}else{
								if(value.indexOf("http://")<0){
									value = "http://" + netUrl.getHost() + "/" + value;
								}
							}
						}
						if (StringUtils.isNotEmpty(detail.getLink()) && detail.getAttr().equals("href")) {
							this.getChildPage(detail.getLink(), detail.getUser_id(), h2dao, value, 0);
						}
					}

					int c = Math.max(temp.getRows(), array.size());

					for (int i = 0; i < c; i++) {
						if ((i + 1) > array.size()) {
							JSONObject json = new JSONObject();
							json.put(k, value);
							if (StringUtils.isNotEmpty(detail.getLink())) {
								JSONObject link = new JSONObject();
								JSONObject var = new JSONObject();
								var.put("url", value);
								var.put("rid", detail.getLink());
								link.put(k, var);
								json.put("link", link);
							}
							array.add(json);
						} else {
							JSONObject json = array.getJSONObject(i);
							json.put(k, value);
							if (StringUtils.isNotEmpty(detail.getLink())) {
								JSONObject link = json.getJSONObject("link");
								if (link == null) {
									link = new JSONObject();
								}
								JSONObject var = link.getJSONObject(k);
								if (var == null) {
									var = new JSONObject();
								}
								var.put("url", value);
								var.put("rid", detail.getLink());
								link.put(k, var);
								json.put("link", link);
							}
						}
					}
				}

			}
			LOGGER.info("#########页面解析单元-ELE素完成" + request_id + "##############");

			/**
			 * 处理附加属性
			 */
			for (String k : keys) {
				if (k.equals("url")) {
					for (int i = 0; i < array.size(); i++) {
						JSONObject json = array.getJSONObject(i);
						json.put("url", url);
					}
				}

				for (int i = 0; i < exts; i++) {
					if (k.equals("ext" + i)) {
						String[] value = extList.get(i);
						String eh = value[0];
						String ev = value[1];
						if (eh.equals("id")) {
							String[] es = ev.split("#");
							String index = es[1];
							String last = es[2];
							if (es[0].equals("url")) {
								String tempUrl = url;
								String page_id = tempUrl.substring(index.length(),
										tempUrl.lastIndexOf(last) + last.length());
								ev = page_id;
							}
						}
						for (int j = 0; j < array.size(); j++) {
							JSONObject json = array.getJSONObject(j);
							json.put(k, ev);
						}

					}
				}

			}

			LOGGER.info("#########页面解析附加属性-EXT完成" + request_id + "##############");
			return array;
		} catch (Exception e) {
			throw new Exception(e);
		}

	}

	private void getChildPage(String linkRequestId, Long user_id, Dao h2dao, String url, int i) {
		if (StringUtils.isNotEmpty(url)) {
			NutDao apiDao = SpringContextHolder.getBean("dao");

			apiDao.clear(TemplateUrl.class, Cnd.where("request_id", "=", linkRequestId).and("url", "=", url));
			TemplateUrl tpurl = new TemplateUrl();
			tpurl.setRequest_id(linkRequestId);
			tpurl.setUser_id(user_id);
			tpurl.setStatus(1);
			tpurl.setUrl(url);
			tpurl.setOrderby(i);
			tpurl.setCreate_time(new Date());
			tpurl.setSend_status(1);
			apiDao.fastInsert(tpurl);
			//template_url 改用python,redis 存储
//			if (h2dao!=null) {
//				H2Urls urls = new H2Urls();
//				urls.setId(tpurl.getId());
//				urls.setUser_id(tpurl.getUser_id());
//				urls.setRequest_id(tpurl.getRequest_id());
//				urls.setUrl(url);
//				urls.setIsjs("0");
//				urls.setCreate_time(new Date());
//				urls.setType("url");
//				TQueue.getQueue().add(urls);
//				h2dao.fastInsert(urls);
//			}

		}
	}

	public String getValue(String attr, Element node) {
		String value = "";
		if (attr.equals("text")) {
			value = node.text();
		} else {
			value = node.attr(attr);
		}

		if (StringUtils.isEmpty(value)) {
			Elements childNodes = node.children();
			while (childNodes.size() > 0) {
				for (Element tmp : childNodes) {
					childNodes = tmp.children();
					if (attr.equals("text")) {
						value = tmp.text();
					} else {
						value = tmp.attr(attr);
					}

					if (StringUtils.isNotEmpty(value)) {
						break;
					}
				}
				if (StringUtils.isNotEmpty(value)) {
					break;
				}
			}
		}
		return value;

	}

	public static void main(String[] args) throws Exception {
		Const.PHANTOMJS_PATH = "D:\\phantomjs-2.1.1-windows\\bin\\phantomjs.exe";
		WebDriver driver = PhantomjsUtilV2.getDriver();

		String url = "https://www.yingzt.com/invest/list";
		driver.get(url);

		JavascriptExecutor js = (JavascriptExecutor) driver;
		// 获取网页高度，用于滚动到底部，防止仅加载一部分数据
		Long height = (Long) js.executeScript("return document.body.scrollHeight");

		Dimension POPULAR_DISPLAY_SIZE = new Dimension(3000, height.intValue());
		driver.manage().window().setSize(POPULAR_DISPLAY_SIZE);
		try {
			js.executeScript("scrollTo(0,30000)");
		} catch (Exception E) {

		}
		// TimeUnit.SECONDS.sleep(10);
		driver.findElement(By.cssSelector("#yw0 > a.next:nth-child(1)")).click();
		String html = driver.getPageSource();

		Document doc = Jsoup.parse(html);
		/// >div.body>div.comment>div>div.media>div.media-body>div.comment-content
		Elements es = doc.select(
				"https://www.yingzt.com/invest/list");
		System.out.println(es);

	}

}
